package server.util.panel;

import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import javax.swing.JPanel;
import server.display.ClientControl;
import util.StringMetrics;

public class ClientControlPianoPanel extends JPanel implements MouseMotionListener, MouseListener {

    ClientControl clientControl;

    private Rectangle[] whiteKeys;
    private Rectangle[] blackKeys;

    private Rectangle mouseOver;

    private String[] whiteKeyNames = {"C", "D", "E", "F", "G", "A", "B"};
    private int[] whiteKeyFrequencies = {261, 293, 329, 349, 392, 440, 493};
    
    private String[] blackKeyNames = {"C#", "D#", "F#", "G#", "A#"};
    private int[] blackKeyFrequencies = {277, 311, 369, 415, 466};
    
    public ClientControlPianoPanel() {
        super();
        
        whiteKeys = new Rectangle[whiteKeyNames.length];
        blackKeys = new Rectangle[blackKeyNames.length];

        mouseOver = null;

        for (int i = 0; i < whiteKeys.length; i++) {
            whiteKeys[i] = new Rectangle(80 * i, 0, 80, 400);
        }

        for (int i = 0; i < blackKeys.length; i++) {
            if (i > 2) {
                blackKeys[i] = new Rectangle(80 * (i + 1) + 60, 0, 40, 240);
            } else {
                blackKeys[i] = new Rectangle(80 * i + 60, 0, 40, 240);
            }
        }

        this.addMouseListener(this);
        this.addMouseMotionListener(this);
    }

    public void setClientControl (ClientControl clientControl) {
        this.clientControl = clientControl;
    }

    @Override
    public void paintComponent(Graphics g) {
        super.paintComponent(g);

        g.setColor(Color.WHITE);
        for (Rectangle key : whiteKeys) {
            g.fillRect(key.x, key.y, key.width, key.height);
        }

        // Border and key names
        g.setFont(new Font("Arial", Font.PLAIN, 24));
        for (int i = 0; i < whiteKeys.length; i++) {
            g.setColor(Color.BLACK);

            Rectangle key = whiteKeys[i];
            int nameWidth = StringMetrics.getWidth((Graphics2D) g, whiteKeyNames[i]);

            g.drawString(whiteKeyNames[i], key.x + key.width / 2 - nameWidth / 2, key.y + key.height - 30);
            g.drawRect(key.x, key.y, key.width, key.height);

            if (mouseOver != null && key.equals(mouseOver)) {
                g.setColor(new Color(0, 190, 255));
                g.drawRect(key.x + 1, key.y + 1, key.width - 2, key.height - 2);
                g.drawRect(key.x + 2, key.y + 2, key.width - 4, key.height - 4);
            }
        }

        g.setColor(Color.BLACK);
        for (Rectangle key : blackKeys) {
            g.fillRect(key.x, key.y, key.width, key.height);
        }
        
        g.setFont(new Font("Arial", Font.PLAIN, 14));
        for (int i = 0; i < blackKeys.length; i++) {
            g.setColor(Color.WHITE);
            
            Rectangle key = blackKeys[i];
            int nameWidth = StringMetrics.getWidth((Graphics2D) g, blackKeyNames[i]);

            g.drawString(blackKeyNames[i], key.x + key.width / 2 - nameWidth / 2, key.y + key.height - 20);
            
            if (mouseOver != null && key.equals(mouseOver)) {
                g.setColor(new Color(0, 190, 255));
                g.drawRect(key.x, key.y, key.width - 1, key.height - 1);
                g.drawRect(key.x + 1, key.y + 1, key.width - 3, key.height - 3);
            }
        }

    }

    @Override
    public void mouseDragged(MouseEvent e) {
    }

    @Override
    public void mouseMoved(MouseEvent e) {
        mouseOver = null;
        
        outerloop:
        for (Rectangle whiteKey : whiteKeys) {
            if (whiteKey.contains(e.getPoint())) {
                mouseOver = whiteKey;
                break;
            } else {
                for (Rectangle blackKey : blackKeys) {
                    if (blackKey.contains(e.getPoint())) {
                        mouseOver = blackKey;
                        break outerloop;
                    }
                }
            }
        }

        repaint();
    }

    @Override
    public void mouseClicked(MouseEvent e) {
        Rectangle clicked = null;
        int clickedIndex = 0;
        boolean white = true;
        
        outerloop:
        for (int i = 0; i < whiteKeys.length; i++) {
            Rectangle whiteKey = whiteKeys[i];
            
            if (whiteKey.contains(e.getPoint())) {
                clicked = whiteKey;
                clickedIndex = i;
                white = true;
                break;
            } else {
                for (int j = 0; j < blackKeys.length; j++) {
                    Rectangle blackKey = blackKeys[j];
                    
                    if (blackKey.contains(e.getPoint())) {
                        clicked = blackKey;
                        clickedIndex = j;
                        white = false;
                        break outerloop;
                    }
                }
            }
        }
        
        if (clicked != null && e.getButton() == MouseEvent.BUTTON1) {
            if (white) {
                clientControl.pianoPlaySound(whiteKeyFrequencies[clickedIndex]);
            } else {
                clientControl.pianoPlaySound(whiteKeyFrequencies[clickedIndex]);
            }
        }
    }

    @Override
    public void mousePressed(MouseEvent e) {
    }

    @Override
    public void mouseReleased(MouseEvent e) {
    }

    @Override
    public void mouseEntered(MouseEvent e) {
    }

    @Override
    public void mouseExited(MouseEvent e) {
        mouseOver = null;
        repaint();
    }

}
